package cinema;

import java.util.*;
import java.util.stream.Collectors;

public class Receptionist extends User {
    public Receptionist(String userId, String username, String password, Date registerTime,
                        String userType, String phone) {
        super(userId, username, password, registerTime, userType, phone);
    }

    // 售票功能
    public Ticket sellTicket(List<Schedule> schedules, String scheduleId, List<String> seatNumbers) {
        Optional<Schedule> scheduleOpt = findSchedule(schedules, scheduleId);
        if (scheduleOpt.isEmpty()) {
            System.out.println("未找到该场次");
            return null;
        }

        Schedule schedule = scheduleOpt.get();
        Hall hall = schedule.getHall();

        // 验证所有座位是否可用
        if (!areSeatsAvailable(hall, seatNumbers)) {
            return null;
        }

        // 锁定座位
        reserveSeats(hall, seatNumbers);

        // 计算票价
        double price = calculatePrice(schedule, seatNumbers.size());

        // 创建票务信息
        Ticket ticket = createTicket(schedule, seatNumbers, price);
        System.out.println("售票成功，总金额：" + price);
        System.out.println(ticket.getTicketInfo());

        return ticket;
    }

    // 退票功能
    public boolean refundTicket(List<Ticket> tickets, String ticketId, List<Schedule> schedules) {
        Optional<Ticket> ticketOpt = findTicket(tickets, ticketId);
        if (ticketOpt.isEmpty()) {
            System.out.println("未找到该票或已退票");
            return false;
        }

        Ticket ticket = ticketOpt.get();
        Schedule schedule = ticket.getSchedule();

        // 验证场次信息
        if (schedule == null || !schedules.contains(schedule)) {
            System.out.println("该票对应的场次信息不存在，无法退票");
            return false;
        }

        // 检查退票时间限制
        if (!isRefundAllowed(schedule)) {
            return false;
        }

        // 计算退票金额
        double refundAmount = calculateRefundAmount(ticket, schedule);

        // 释放座位
        releaseSeats(schedule.getHall(), ticket.getSeat());

        // 更新票状态
        ticket.setRefunded(true);

        // 记录日志
        logRefundOperation(ticketId, ticket.getPrice(), refundAmount);

        return true;
    }

    // 列出所有场次（按时间排序）
    public void listAllSchedules(List<Schedule> schedules) {
        if (schedules.isEmpty()) {
            System.out.println("当前没有排片");
            return;
        }

        System.out.println("当前排片表：");
        schedules.stream()
                .sorted(Comparator.comparing(Schedule::getTime))
                .forEach(this::printScheduleInfo);
    }

    // 查看座位状态
    public void viewSeatsStatus(Schedule schedule) {
        if (schedule == null) {
            System.out.println("无效场次信息");
            return;
        }

        Hall hall = schedule.getHall();
        System.out.println("影厅：" + hall.getHallName());
        System.out.println("影片：" + schedule.getMovie().getName());
        System.out.println("时间：" + schedule.getTime());
        System.out.println("座位状态（O-空闲，X-已售）：");

        printSeatMap(hall);
    }

    //============ 辅助方法 ============//
    private Optional<Schedule> findSchedule(List<Schedule> schedules, String scheduleId) {
        return schedules.stream()
                .filter(s -> s.getScheduleId().equals(scheduleId))
                .findFirst();
    }

    private boolean areSeatsAvailable(Hall hall, List<String> seatNumbers) {
        for (String seat : seatNumbers) {
            SeatPosition position = parseSeatPosition(seat);
            if (position == null || !isSeatAvailable(hall, position)) {
                System.out.println("座位" + seat + "不可用");
                return false;
            }
        }
        return true;
    }

    private void reserveSeats(Hall hall, List<String> seatNumbers) {
        for (String seat : seatNumbers) {
            SeatPosition position = parseSeatPosition(seat);
            hall.updateSeat(position.row(), position.column(), "X");
        }
    }

    private double calculatePrice(Schedule schedule, int seatCount) {
        double basePrice = schedule.getPrice() * seatCount;
        Date showTime = schedule.getTime();

        // 早场折扣（10点前）
        if (showTime.getHours() <= 10) {
            return basePrice * 0.9;
        }
        return basePrice;
    }

    private Ticket createTicket(Schedule schedule, List<String> seatNumbers, double price) {
        String seats = String.join(",", seatNumbers);
        return new Ticket(schedule.getMovie(), schedule, seats, price);
    }

    private Optional<Ticket> findTicket(List<Ticket> tickets, String ticketId) {
        return tickets.stream()
                .filter(t -> t.getTicketId().equals(ticketId) && !t.isRefunded())
                .findFirst();
    }

    private boolean isRefundAllowed(Schedule schedule) {
        Date now = new Date();
        Date showTime = schedule.getTime();
        long diff = showTime.getTime() - now.getTime();

        if (diff < 3600000) { // 小于1小时
            System.out.println("距离放映时间不足1小时，不允许退票");
            return false;
        }
        return true;
    }

    private double calculateRefundAmount(Ticket ticket, Schedule schedule) {
        Date now = new Date();
        Date showTime = schedule.getTime();
        long diff = showTime.getTime() - now.getTime();

        double refundRate = 1.0; // 默认全额退款
        if (diff < 24 * 3600000) { // 24小时内
            refundRate = 0.9; // 扣10%手续费
        } else if (diff < 48 * 3600000) { // 48小时内
            refundRate = 0.95; // 扣5%手续费
        }

        double refundAmount = ticket.getPrice() * refundRate;
        System.out.printf("退票成功，票号：%s%n原票价：%.2f元，退票金额：%.2f元%n退票时间：%s%n",
                ticket.getTicketId(), ticket.getPrice(), refundAmount, now);
        return refundAmount;
    }

    private void releaseSeats(Hall hall, String seatString) {
        String[] seats = seatString.split(",");
        for (String seat : seats) {
            SeatPosition position = parseSeatPosition(seat);
            if (position != null) {
                hall.updateSeat(position.row(), position.column(), "O");
            }
        }
    }

    private void logRefundOperation(String ticketId, double originalPrice, double refundAmount) {
        String operation = String.format("退票操作，票号：%s (原价: %.2f, 退款: %.2f)",
                ticketId, originalPrice, refundAmount);
        new Log(operation, this.getUsername()).recordLog();
    }

    private void printScheduleInfo(Schedule schedule) {
        System.out.printf("场次ID：%s | 影片：%s | 影厅：%s | 时间：%s | 票价：%.2f%n",
                schedule.getScheduleId(),
                schedule.getMovie().getName(),
                schedule.getHall().getHallName(),
                schedule.getTime(),
                schedule.getPrice());
    }

    private void printSeatMap(Hall hall) {
        String[][] seats = hall.getSeatsStatus();
        int rows = hall.getRow();
        int columns = hall.getColumn();

        // 打印列号标题
        System.out.print("   ");
        for (int col = 0; col < columns; col++) {
            System.out.printf("%2d ", col + 1);
        }
        System.out.println();

        // 打印行号和座位状态
        for (int row = 0; row < rows; row++) {
            System.out.printf("%2d ", row + 1);
            for (int col = 0; col < columns; col++) {
                System.out.print(" " + seats[row][col] + " ");
            }
            System.out.println();
        }
    }

    private SeatPosition parseSeatPosition(String seat) {
        try {
            // 支持多种格式：3排5号 或 3-5
            if(seat.contains("排")) {
                String[] parts = seat.split("排");
                int row = Integer.parseInt(parts[0]) - 1;
                int col = Integer.parseInt(parts[1].replace("号", "")) - 1;
                return new SeatPosition(row, col);
            } else if(seat.contains("-")) {
                String[] parts = seat.split("-");
                int row = Integer.parseInt(parts[0]) - 1;
                int col = Integer.parseInt(parts[1]) - 1;
                return new SeatPosition(row, col);
            }
            throw new Exception();
        } catch (Exception e) {
            System.out.println("无效座位格式：" + seat + "，请使用'3排5号'或'3-5'格式");
            return null;
        }
    }

    private boolean isSeatAvailable(Hall hall, SeatPosition position) {
        String[][] seats = hall.getSeatsStatus();
        return seats[position.row()][position.column()].equals("O");
    }

    // 座位位置记录
    private record SeatPosition(int row, int column) {}
}